package com.shop.socket.udp;

import java.io.IOException;
import java.net.*;
import java.nio.charset.StandardCharsets;

/**
 * @author Song Yinghui
 * @date 2019/12/13
 * @Version 1.0
 *
 *  udp 协议
 *  UDP数据报分为首部和用户数据部分，整个UDP数据报作为IP数据报的数据部分封装在IP数据报中，UDP数据报文结构如图所示
 *  UDP首部有8个字节，由4个字段构成，每个字段都是两个字节，
 * 1.源端口： 源端口号，需要对方回信时选用，不需要时全部置0.
 * 2.目的端口：目的端口号，在终点交付报文的时候需要用到。
 * 3.长度：UDP的数据报的长度（包括首部和数据）其最小值为8（只有首部）
 * 4.校验和：检测UDP数据报在传输中是否有错，有错则丢弃。
 * 该字段是可选的，当源主机不想计算校验和，则直接令该字段全为0.
 * 当传输层从IP层收到UDP数据报时，就根据首部中的目的端口，把UDP数据报通过相应的端口，上交给应用进程。
 * 如果接收方UDP发现收到的报文中的目的端口号不正确（不存在对应端口号的应用进程0,），就丢弃该报文，并由ICMP发送“端口不可达”差错报文给对方。
 */


public class UdpClient {

    /**
     * 简而言之，udp报文中会携带该数据包要发往何处的ip、端口信息，因此需要将此信息放在数据包中
     * @throws SocketException
     */
    public void strat() throws IOException {

        int port = 10000; //本地启动发送udp数据包服务时所需要的一个端口 可指定固定的端口，如果不指定，则随机占用一个可用的端口
        DatagramSocket udpSocket = new DatagramSocket();

        for (int i = 0; i < 10; i++) {
            String sendMessage = "I'm client , This is message that client send! ";
            DatagramPacket packet = new DatagramPacket(sendMessage.getBytes(StandardCharsets.UTF_8), sendMessage.getBytes().length,
                    InetAddress.getByName("127.0.0.1"), 5556);
            udpSocket.send(packet);
            System.out.println("send "+i+" is completed!");
            byte[] buff = new byte[1024];
            DatagramPacket receivePacket = new DatagramPacket(buff, buff.length);
            udpSocket.receive(receivePacket);
            System.out.println("received "+i+" is completed!\t"+new String(receivePacket.getData(), 0, receivePacket.getLength(), StandardCharsets.UTF_8));
        }
        udpSocket.close();
    }

    public static void main(String[] args) throws IOException {
        new UdpClient().strat();
    }
}
